const vertSrc =
`#version 300 es

layout (location = 0) in vec2 pos;

void main()
{
    gl_Position = vec4(pos.xy, 0.0, 1.0);
}
`

const getFragSrc = (width, height) =>
`#version 300 es

precision mediump float;

const uint WIDTH = ${width}u, HEIGHT = ${height}u;

uniform uint[64] T;
uniform int[64] s;
uniform int[64] m;
uniform uvec4 target;

out vec4 result;

void main()
{
    uint idx = uint(gl_FragCoord.y) * WIDTH + uint(gl_FragCoord.x);

    uint data[16];
    data[0] = (48u + idx % 1000000u / 100000u) |
        ((48u + idx % 100000u / 10000u) << 8) |
        ((48u + idx % 10000u / 1000u) << 16) |
        ((48u + idx % 1000u / 100u) << 24);
    data[1] = (48u + idx % 100u / 10u) |
        ((48u + idx % 10u) << 8) |
        (0x80u << 16);
    for (int i = 2; i < 16; i++) data[i] = 0u;
    data[14] = 48u;

    uvec4 outp = uvec4(0x67452301u, 0xEFCDAB89u, 0x98BADCFEu, 0x10325476u);

    {
        int i = 0;

        uvec4 ABCD = outp;

        for (int j = 0; j < 64; j++)
        {
            uint F;
            switch (j / 16)
            {
            case 0:
                F = (ABCD.y & ABCD.z) | ((~ABCD.y) & ABCD.w);
                break;
            case 1:
                F = (ABCD.w & ABCD.y) | ((~ABCD.w) & ABCD.z);
                break;
            case 2:
                F = ABCD.y ^ ABCD.z ^ ABCD.w;
                break;
            case 3:
                F = ABCD.z ^ (ABCD.y | (~ABCD.w));
                break;
            }
            uint sum = ABCD.x + F + data[i + m[j]] + T[j];
            ABCD.x = ABCD.w;
            ABCD.w = ABCD.z;
            ABCD.z = ABCD.y;
            ABCD.y += (sum << s[j]) | (sum >> (32 - s[j]));
        }

        outp += ABCD;
    }

    if (outp == target) result = vec4(1.0, 1.0, 1.0, 1.0);
    else result = vec4(0.0, 0.0, 0.0, 1.0);
}
`
